package com.tungse.study.threadpool;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author Tungse
 */
public class MyThreadPool {


    //核心线程数量
    private int corePoolSize = 10;
    //线程池总线程数
    private int maxPoolSize = 15;
    //线程池最大等待时间
    private long keepAliveTime = 1;
    private TimeUnit timeUnit = TimeUnit.SECONDS;
    //任务池
    public BlockingQueue<Runnable> runnableQueue;
    //拒绝策略
    private RejectHandle rejectHandle;


    //核心线程池
    List<Thread> coreList = new ArrayList<>(corePoolSize);
    //辅助线程池
    List<Thread> supportList = new ArrayList<>(corePoolSize);

    public MyThreadPool() {

    }

    public MyThreadPool(int corePoolSize, int maxPoolSize, long keepAliveTime,
                        TimeUnit timeUnit, BlockingQueue<Runnable> runnableQueue,
                        RejectHandle rejectHandle) {
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;
        this.keepAliveTime = keepAliveTime;
        this.timeUnit = timeUnit;
        this.runnableQueue = runnableQueue;
        this.rejectHandle = rejectHandle;
    }

    public void execute(Runnable runnable) {
        if (coreList.size() < corePoolSize) {
            Thread thread = new CoreThread();
            coreList.add(thread);
            thread.start();
        }
        if (runnableQueue.offer(runnable)) {
            return;
        }
        if ((coreList.size() + supportList.size()) < maxPoolSize) {
            Thread thread = new SupportThread();
            supportList.add(thread);
            thread.start();
        }
        if (!runnableQueue.offer(runnable)) {
            rejectHandle.reject(runnable, this);
//            throw new RuntimeException("线程池已满");
        }
    }

    public class CoreThread extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    Runnable runnable = runnableQueue.take();
                    runnable.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public class SupportThread extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    Runnable runnable = runnableQueue.poll(keepAliveTime, timeUnit);
                    if (runnable == null) {
                        break;
                    }
                    runnable.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(this.getName() + "结束了");
        }

    }
}
